﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Development.DataEntity;

namespace Development.Factory
{
    public class DataContainer : IDisposable
    {
        protected ConcurrentDictionary<long, DataEntityBase> _datas = new ConcurrentDictionary<long, DataEntityBase>();

        protected System.Timers.Timer _expirationTimer = null;
        protected System.Timers.Timer _rankingTimer = null;
        protected int _expirationHour = 0;
        public void StartCheckExpiration(int hour)
        {
            _expirationHour = hour;
            _expirationTimer = new System.Timers.Timer(hour * 60 * 60 * 1000);
            _expirationTimer.Elapsed += _timer_Elapsed;
            _expirationTimer.Start();
        }

        public void StartRanking(int seconds)
        {
            _rankingTimer = new System.Timers.Timer(seconds * 1000);
            _rankingTimer.Elapsed += _rankingTimer_Elapsed;
            _rankingTimer.Start();
        }

        void _rankingTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            List<DataEntityBase> list = new List<DataEntityBase>(_datas.Values);
            list.Sort();
            for(int i = 0; i < list.Count; ++i)
            {
                DataEntityBase ent = list[i];
                ent.ModifyLock <DataEntityBase>(temp =>
                {
                    temp.Rank = i + 1;
                });
            }
        }

        void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            List<DataEntityBase> list = new List<DataEntityBase>(_datas.Values);
            for(int i = 0; i < list.Count;++i)
            {
                DataEntityBase t = list[i];
                if((DateTime.Now - t.UseTime).TotalHours >= _expirationHour)
                {
                    _datas.TryRemove(t.ID, out t);
                }
            }
        }

        public void Add(long key,DataEntityBase t)
        {
            _datas.TryAdd(key, t);
        }

        public void Add<T>(long key, T val) where T : DataEntityBase
        {
            _datas.TryAdd(key, val);
        }
        public T Get<T>(long key) where T : DataEntityBase
        {
            DataEntityBase t = null;
            _datas.TryGetValue(key, out t);
            return t as T;
        }

        public List<T> Get<T>(List<long> keys) where T : DataEntityBase
        {
            List<T> list = GetAll<T>();
            return list.FindAll(p=>keys.Contains(p.ID));
        }

     
        public T Remove<T>(long key) where T : DataEntityBase
        {
            DataEntityBase t = null;
            _datas.TryRemove(key, out t);
            return t as T;
        }

        public void Remove<T>(List<T> ts) where T : DataEntityBase
        {
            for(int i = 0;i < ts.Count;++i)
            {
                Remove<T>(ts[i].ID);
            }
        }

        public List<T> GetAll<T>() where T : DataEntityBase
        {
            List<DataEntityBase> list = new List<DataEntityBase>(_datas.Values);
            List<T> result = new List<T>();
            for(int i = 0; i < list.Count;++i)
            {
                result.Add(list[i] as T);
            }
            return result;
        }

        public List<T> GetAll<T>(Predicate<T> match) where T : DataEntityBase
        {
            List<T> list = GetAll<T>();
            return list.FindAll(match);
        }

        public List<long> GetKeys<T>() where T : DataEntityBase
        {
            List<long> keys = new List<long>(_datas.Keys);
            return keys;
        }

        public int Count
        {
            get { return _datas.Count; }
        }

        public void Clear()
        {
            _datas.Clear();
        }

        public void Dispose()
        {
            if (_expirationTimer != null)
            {
                _expirationTimer.Stop();
            }

            if(_rankingTimer != null)
            {
                _rankingTimer.Stop();
            }
        }
    }
}
